using Microsoft.Xna.Framework;
using Rocuna.Graphics.Constants;
using Rocuna.Graphics.Core;

namespace WindowsGameLibrary1.Cameras
{
    /// <summary>
    /// Free camera for First Person Shooter.
    /// </summary>
    public class FreeCamera : Camera
    {
        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="FreeCamera"/> class.
        /// </summary>
        public FreeCamera(Vector3 position, float yaw, float pitch, Game game)
            : base(game)
        {
            Position = position;
            Yaw = yaw;
            Pitch = pitch;

            _traslation = Vector3.Zero;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the yaw.
        /// </summary>
        /// <value>
        /// The yaw.
        /// </value>
        public float Yaw { get; set; }

        /// <summary>
        /// Gets or sets the pitch.
        /// </summary>
        /// <value>
        /// The pitch.
        /// </value>
        public float Pitch { get; set; }

        #endregion

        #region fields

        private Vector3 _traslation;

        #endregion

        #region Overrides of Camera

        /// <summary>
        /// Gets the name.
        /// </summary>
        public override string Name
        {
            get { return CamerasNames.FreeCamera; }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Rotates the specified yaw change.
        /// </summary>
        /// <param name="yawChange">The yaw change.</param>
        /// <param name="pitchChange">The pitch change.</param>
        public void Rotate(float yawChange, float pitchChange)
        {
            Yaw += yawChange;
            Pitch += pitchChange;
        }

        /// <summary>
        /// Moves the specified translation.
        /// </summary>
        /// <param name="translation">The translation.</param>
        public void Move(Vector3 translation)
        {
            _traslation += translation;
        }

        #endregion

        #region GameComponent override

        /// <summary>
        /// Called when the GameComponent needs to be updated. Override this method with component-specific update code.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to Update</param>
        public override void Update(GameTime gameTime)
        {
            var rotation = Matrix.CreateFromYawPitchRoll(Yaw, Pitch, 0);

            _traslation = Vector3.Transform(_traslation, rotation);
            Position += _traslation;
            _traslation = Vector3.Zero;

            var forward = Vector3.Transform(Vector3.Forward, rotation);
            Target = Position + forward;

            var up = Vector3.Transform(Vector3.Up, rotation);

            View = Matrix.CreateLookAt(Position, Target, up);
        }

        #endregion
    }
}